﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Polly;
using Resilience;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace User.Identity.Infrastructure
{
    public class ResilienceHttpClientFactory
    {
        private ILogger<ResilientHttpClient> _logger;
        private IHttpContextAccessor _httpContextAccessor;
        private int _retryCount;
        private  int _exceptionCountAllowedBeforeBreacking;

        public ResilienceHttpClientFactory(ILogger<ResilientHttpClient> logger, IHttpContextAccessor httpContextAccessor, int retryCount,int exceptionCountAllowedBeforeBreacking)
        {
            _logger = logger;
            _httpContextAccessor = httpContextAccessor;
            _retryCount = retryCount;
            _exceptionCountAllowedBeforeBreacking = exceptionCountAllowedBeforeBreacking;
        }

        public ResilientHttpClient GetResilienceHttpClient()
        {
            return new ResilientHttpClient(origin => CreatePolicy(origin), _logger, _httpContextAccessor);
        }

        private Policy[] CreatePolicy(string origin)
        {
            return new Policy[]{
                Policy.Handle<HttpRequestException>().WaitAndRetryAsync(
                    _retryCount,
                    retryAttempt=>TimeSpan.FromSeconds(Math.Pow(2,retryAttempt)),
                (exception,timeSpan,retryCount,context)=>
                {
                    var msg=$"第{retryCount}implemented with polly's  retryPolicy"+
                    $"of {context.PolicyKey}"+
                    $"at {context.ExecutionKey}"+
                    $"due to:{exception}.";
                    _logger.LogWarning(msg);
                    _logger.LogDebug(msg);
                }
                ),
                Policy.Handle<HttpRequestException>().CircuitBreakerAsync(_exceptionCountAllowedBeforeBreacking,TimeSpan.FromMinutes(1),
                (excpeiton,duration)=>{
                    _logger.LogTrace("熔断器打开");
                },()=>
                {
                   _logger.LogTrace("熔断器关闭");
                })

        };
        }
    }
}
